package cs236369.webserver;

import java.io.IOException;
import java.net.Socket;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpMessage;
import org.apache.http.HttpRequest;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;

/**
 * 
 * @author artem
 * This class represents the sockets reader threads handler of the server
 * 
 * 
 */
public class SocketReaderHandler implements Runnable {


	private Socket socket;
	private ThreadPool requestPool;
	
	/**
	 * provide the socket queue to wait on
	 */
	
	public SocketReaderHandler(Socket _socket, ThreadPool _threadPool) {
		socket = _socket;
		requestPool = null;
	}
	
	private void getHttpParams(Map<String, String> httpParams,
			HttpRequest httpRequest) {
		
		for (Header h : httpRequest.getAllHeaders()){
			httpParams.put(h.getName().toLowerCase(),h.getValue().toLowerCase());
		}
		
	}

	@Override
	public void run() {
		if (socket == null){
			//there were no sockets waiting in the queue so we wait on it again
			throw new RuntimeException("Null Socket");
		}
		
		DefaultHttpServerConnection serverConn = new DefaultHttpServerConnection();
		HttpParams params = new BasicHttpParams();
		HttpRequest httpRequest;
		try {
			serverConn.bind(socket, params);
			serverConn.setSocketTimeout(5000);
			httpRequest = serverConn.receiveRequestHeader();
		} catch (HttpException e) {
			//TODO: check this
			e.printStackTrace();
			throw new RuntimeException();
		} catch (IOException e) {
			//TODO: check this
			e.printStackTrace();
			throw new RuntimeException();
		}
		Map<String, String> httpParams = new HashMap<String, String>();
		getHttpParams(httpParams, httpRequest);
		String url = httpRequest.getRequestLine().getUri();
		String host = getHeaderValue(httpRequest,"HOST");
		int dotPos = host.indexOf(":");
		if (dotPos > -1) host = host.substring(0, dotPos);
		String httpMethod = httpRequest.getRequestLine().getMethod().toUpperCase();
		Request request = new Request(socket, url, httpParams, httpMethod);
		try {
			requestPool.addTask(new RequestHandler(request));
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
		
	}

	/**
	 * This method returns the value of a specific header from our packet.
	 * If the header doesn't exist returns ""
	 */
	private String getHeaderValue(HttpMessage message,String name) {
		
		// removing white spaces in the header name and turning it to uppercase
		String procName = "";
		StringTokenizer st = new StringTokenizer(name," ",false);
		while (st.hasMoreElements()) procName += st.nextToken();
		procName = procName.toUpperCase(Locale.ENGLISH);
		
		String value = "";
		for(Header header:message.getAllHeaders()) {
			String currHeaderName = header.getName().toUpperCase(Locale.ENGLISH);
			if (currHeaderName.equals(procName)){
				value = header.getValue();
			}
		}
		
		return value.replaceAll(" ", ""); 
	}

}
